package com.huawei.account.service;

import com.alibaba.fastjson2.JSONObject;
import com.huawei.account.entity.response.*;
import com.huawei.account.util.CallUtils;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import com.huawei.account.config.AGCProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class HuaweiLoginService {
    private final AGCProperties agcProperties;
    // 注入RestTemplate（来自配置类的Bean）

    // 注入华为配置（已有的配置类）
    /**
     * 通过华为Authorization Code登录
     */
    @Transactional
    public  HuaweiTokenResp getAPPAccessToken() {
        // 1. 通过Authorization Code获取Access Token/IdToken
        String url = "https://oauth-login.cloud.huawei.com/oauth2/v3/token";
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("grant_type", "client_credentials"));
        request.add(new BasicNameValuePair("client_id", agcProperties.getClientId()));
        request.add(new BasicNameValuePair("client_secret", agcProperties.getClientSecret()));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(request));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        HuaweiTokenResp getAppAccessTokenResp = new HuaweiTokenResp();
        try {
            // 调用工具类，捕获可能的IOException
            String responseStr = CallUtils.remoteCallOAuth(httpPost);
            getAppAccessTokenResp = this.parseAppTokenResponse(responseStr);

            if (getAppAccessTokenResp == null) {
                log.error("从华为服务器获取用户信息失败");
                throw new RuntimeException("获取用户信息失败");
            }

        } catch (Exception e) {
            log.error("<从华为服务器获取用户信息失败>", e);

        }
        return getAppAccessTokenResp;
    }


    /**
     * 通过华为Authorization Code登录
     */
    @Transactional
    public HuaweiTokenResp loginWithAuthorizationCode(String authorizationCode) {
        // 1. 通过Authorization Code获取Access Token/IdToken
        String url = "https://oauth-login.cloud.huawei.com/oauth2/v3/token";
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("grant_type", "authorization_code"));
        request.add(new BasicNameValuePair("client_id", agcProperties.getClientId()));
        request.add(new BasicNameValuePair("client_secret", agcProperties.getClientSecret()));
        request.add(new BasicNameValuePair("code", authorizationCode));
        request.add(new BasicNameValuePair("supportAlg", "PS256"));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(request));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        HuaweiTokenResp getAccessTokenResp = new HuaweiTokenResp();
        try {
            // 调用工具类，捕获可能的IOException
            String responseStr = CallUtils.remoteCallOAuth(httpPost);
            getAccessTokenResp = this.parseTokenResponse(responseStr);

            if (getAccessTokenResp == null) {
                log.error("从华为服务器获取用户信息失败");
                throw new RuntimeException("获取用户信息失败");
            }

        } catch (Exception e) {
            log.error("<从华为服务器获取用户信息失败>", e);

        }
        return getAccessTokenResp;
    }


    /**
     * 刷新访问令牌
     */
    @Transactional
    public HuaweiRefreshTokenResp refreshAccessToken(HuaweiTokenResp refreshTokenReq) {
        // 1. 通过Authorization Code获取Access Token/IdToken
        String url = "https://oauth-login.cloud.huawei.com/oauth2/v3/token";
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("grant_type", "refresh_token"));
        request.add(new BasicNameValuePair("client_id", agcProperties.getClientId()));
        request.add(new BasicNameValuePair("client_secret", agcProperties.getClientSecret()));
        request.add(new BasicNameValuePair("refresh_token", refreshTokenReq.getRefresh_token()));
        request.add(new BasicNameValuePair("scope",refreshTokenReq.getScope() ));
        request.add(new BasicNameValuePair("supportAlg", "PS256"));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(request));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        HuaweiRefreshTokenResp RefreshTokenResp = new HuaweiRefreshTokenResp();
        try {
            // 调用工具类，捕获可能的IOException
            String responseStr = CallUtils.remoteCallOAuth(httpPost);
            RefreshTokenResp = this.parseRefreshTokenResponse(responseStr);

            if (RefreshTokenResp == null) {
                log.error("从华为服务器获取用户信息失败");
                throw new RuntimeException("获取用户信息失败");
            }

        } catch (Exception e) {
            log.error("<从华为服务器获取用户信息失败>", e);

        }
        return RefreshTokenResp;
    }

    /**
     * 解析凭证
     */
    @Transactional
    public HuaweiExplainAccessResp ExplainAccessToken(String accessToken) {
        // 1. 通过Authorization Code获取Access Token/IdToken
        String url = "https://oauth-api.cloud.huawei.com/rest.php?nsp_fmt=JSON&nsp_svc=huawei.oauth2.user.getTokenInfo";
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("access_token", accessToken));
        request.add(new BasicNameValuePair("open_id", "OPENID"));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(request));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        HuaweiExplainAccessResp ExplainAccessResp = new HuaweiExplainAccessResp();
        try {
            // 调用工具类，捕获可能的IOException
            String responseStr = CallUtils.remoteCallOAuth(httpPost);
            ExplainAccessResp = this.parseExplainAccessResponse(responseStr);

            if (ExplainAccessResp.getClient_id() == null) {
                log.error("从华为服务器获取用户信息失败");
                throw new RuntimeException("获取用户信息失败");
            }

        } catch (Exception e) {
            log.error("<从华为服务器获取用户信息失败>", e.hashCode());

        }
        return ExplainAccessResp;
    }

    /**
     * 获取用户信息
     */
    @Transactional
    public HuaweiGetUserInfoResp GetUserInfo(String accessToken) {
        // 1. 通过Authorization Code获取Access Token/IdToken
        String url = "https://account.cloud.huawei.com/rest.php?nsp_svc=GOpen.User.getInfo";
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("access_token", accessToken));
        request.add(new BasicNameValuePair("getNickName", String.valueOf(1)));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(request));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        HuaweiGetUserInfoResp getUserInfoResp = new HuaweiGetUserInfoResp();
        try {
            // 调用工具类，捕获可能的IOException
            String responseStr = CallUtils.remoteCallOAuth(httpPost);
            getUserInfoResp = this.parseGetUserInfoResponse(responseStr);

            if (getUserInfoResp == null) {
                log.error("从华为服务器获取用户信息失败");
                throw new RuntimeException("获取用户信息失败");
            }

        } catch (Exception e) {
            log.error("<从华为服务器获取用户信息失败>", e);

        }
        return getUserInfoResp;
    }


    /**
     * 退出登录
     *
     * @return
     */
    @Transactional
    public String LoginOut(String accessToken) throws IOException {
        // 1. 通过Authorization Code获取Access Token/IdToken
        String url = "https://oauth-login.cloud.huawei.com/oauth2/v3/revoke";
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("token", accessToken));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(request));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }


        return CallUtils.remoteCallOAuth(httpPost);
    }

    /**
     * 解析华为Token响应
     */
    HuaweiTokenResp parseAppTokenResponse(String responseStr) {
        try {
            // 使用JSON库解析响应字符串
            JSONObject jsonResponse = CallUtils.toJsonObject(responseStr);

            // 创建并填充HuaweiTokenResp对象
            HuaweiTokenResp tokenResp = new HuaweiTokenResp();

            // 根据华为OAuth API文档设置字段

            tokenResp.setToken_type(jsonResponse.getString("token_type"));

            tokenResp.setAccess_token(jsonResponse.getString("access_token"));


            tokenResp.setExpires_in(jsonResponse.getInteger("expires_in"));

            return tokenResp;
        } catch (Exception e) {
            System.err.println("解析华为Token响应失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 解析华为Token响应
     */
    HuaweiTokenResp parseTokenResponse(String responseStr) {
        try {
            // 使用JSON库解析响应字符串
            JSONObject jsonResponse = CallUtils.toJsonObject(responseStr);

            // 创建并填充HuaweiTokenResp对象
            HuaweiTokenResp tokenResp = new HuaweiTokenResp();

            // 根据华为OAuth API文档设置字段

            tokenResp.setToken_type(jsonResponse.getString("token_type"));

            tokenResp.setAccess_token(jsonResponse.getString("access_token"));

            tokenResp.setScope(jsonResponse.getString("scope"));

            tokenResp.setExpires_in(jsonResponse.getInteger("expires_in"));

            tokenResp.setRefresh_token(jsonResponse.getString("refresh_token"));

            tokenResp.setIdToken(jsonResponse.getString("id_token"));

            return tokenResp;
        } catch (Exception e) {
            System.err.println("解析华为Token响应失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    HuaweiExplainAccessResp parseExplainAccessResponse(String ExplainResponseStr) {
        try {
            // 使用JSON库解析响应字符串
            JSONObject jsonResponse = CallUtils.toJsonObject(ExplainResponseStr);

            // 创建并填充HuaweiTokenResp对象
            HuaweiExplainAccessResp explainResponseStr = new HuaweiExplainAccessResp();

            // 根据华为OAuth API文档设置字段

            explainResponseStr.setClient_id(jsonResponse.getString("client_id"));

            explainResponseStr.setExpire_in(jsonResponse.getString("expire_in"));

// 处理union_id（可能不存在）
            try {
                String unionId = jsonResponse.getString("union_id");
                explainResponseStr.setUnion_id(unionId);
            } catch (Exception e) {
                // 字段不存在或获取失败时的处理
                explainResponseStr.setUnion_id(null); // 或设置为空字符串""
            }

// 处理open_id（可能不存在）
            try {
                Integer openId = jsonResponse.getInteger("open_id");
                explainResponseStr.setOpen_id(openId != null ? String.valueOf(openId) : null);
            } catch (Exception e) {
                explainResponseStr.setOpen_id(null);
            }

// 处理scope（可能不存在）
            try {
                String scope = jsonResponse.getString("scope");
                explainResponseStr.setScope(scope);
            } catch (Exception e) {
                explainResponseStr.setScope(null);
            }

            explainResponseStr.setProject_id(jsonResponse.getString("project_id"));

            explainResponseStr.setType(jsonResponse.getString("type"));

            return explainResponseStr;
        } catch (Exception e) {
            System.err.println("解析华为Token响应失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解析华为Token响应
     */
    HuaweiGetUserInfoResp parseGetUserInfoResponse(String responseStr) {
        try {
            // 使用JSON库解析响应字符串
            JSONObject jsonResponse = CallUtils.toJsonObject(responseStr);

            // 创建并填充HuaweiTokenResp对象
            HuaweiGetUserInfoResp userInfoResp = new HuaweiGetUserInfoResp();

            // 根据华为OAuth API文档设置字段

            userInfoResp.setOpenID(jsonResponse.getString("openID"));

            userInfoResp.setUnionID(jsonResponse.getString("unionID"));

            userInfoResp.setDisplayName(jsonResponse.getString("displayName"));

            userInfoResp.setDisplayNameFlag(String.valueOf(jsonResponse.getInteger("displayNameFlag")));
            try {
                userInfoResp.setHeadPictureURL(jsonResponse.getString("headPictureURL"));
            } catch (Exception e) {
                userInfoResp.setHeadPictureURL(null);
            }
            return userInfoResp;
        } catch (Exception e) {
            System.err.println("解析华为Token响应失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    HuaweiRefreshTokenResp parseRefreshTokenResponse(String refreshResponseStr) {
        try {
            // 使用JSON库解析响应字符串
            JSONObject jsonResponse = CallUtils.toJsonObject(refreshResponseStr);

            // 创建并填充HuaweiTokenResp对象
            HuaweiRefreshTokenResp refreshTokenResp = new HuaweiRefreshTokenResp();

            // 根据华为OAuth API文档设置字段

            refreshTokenResp.setToken_type(jsonResponse.getString("token_type"));

            refreshTokenResp.setAccess_token(jsonResponse.getString("access_token"));

            refreshTokenResp.setScope(jsonResponse.getString("scope"));

            refreshTokenResp.setExpires_in(jsonResponse.getInteger("expires_in"));

            refreshTokenResp.setIdToken(jsonResponse.getString("id_token"));

            return refreshTokenResp;
        } catch (Exception e) {
            System.err.println("解析华为Token响应失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }


}
